import lark from "@larksuiteoapi/node-sdk";
import {execSync} from "child_process";
import {createLogger} from "./Logger.js";
import {DateUtil} from "./DateUtil.js";
import {OPSConstant} from "../constant/OPSConstant.js";
import ansiRegex from "ansi-regex";

export class FeishuBot {
    constructor(chat = OPSConstant.OPS_DEFAULT_CHAT_ID, options = {}) {
        const appId = options.appId || process.env.FEISHU_APP_ID || "cli_a88b12e0b9b51013";
        const appSecret = options.appSecret || process.env.FEISHU_APP_SECRET || "aBRv7CbiWuL7csrMavfLvc5sMW5B4Ky7";
        this.client = new lark.Client({
            appId,
            appSecret,
            disableTokenCache: false
        });
        this.logger = createLogger('FeiShuBot');
        this.chatId = chat;
        this.tenantToken = options.tenantToken || process.env.FEISHU_TENANT_TOKEN || '';
        this.userAccessToken = options.userAccessToken || process.env.FEISHU_USER_ACCESS_TOKEN || '';
    }

    buildRequestOption() {
        if (this.userAccessToken) {
            return lark.withUserAccessToken(this.userAccessToken);
        }
        if (this.tenantToken) {
            return lark.withTenantToken(this.tenantToken);
        }
        return undefined;
    }

    /**
     * 发送部署信息消息
     * @param {Array<{appName: string, desc: string}>} taskApps 应用信息
     * @param {string} linkUrl 发布单链接
     * @param {string} flowName 发布单名字
     * @param {string} env 部署环境
     * @param {string[]} mentionedUserIds 需要推送到的飞书用户ID
     */
    async sendAppLogs(taskApps, flowName, linkUrl, env, mentionedUserIds = [], options = {}) {
        const deployTime = DateUtil.nowFull();
        const {
            title = "📢 应用构建成功",
            introLines = [],
            timeLabel = "部署时间"
        } = options || {};
        const receiveUserIds = Array.isArray(mentionedUserIds)
            ? Array.from(
                new Set(
                    mentionedUserIds
                        .map(id => typeof id === "string" ? id.trim() : "")
                        .filter(id => !!id)
                )
            )
            : [];
        if (receiveUserIds.length === 0) {
            const error = new Error("未提供需要通知的飞书用户，无法发送个人推送");
            this.logger.warn(error.message);
            throw error;
        }
        // 构造富文本内容
        const content = [];

        // 1. 发布单超链接
        content.push([
            {
                tag: "a",
                href: linkUrl,
                text: `📄 ${flowName}`
            }
        ]);

        // 2. 部署环境
        content.push([
            {
                tag: "text",
                text: `🌍 当前环境：${env}`
            }
        ]);
        content.push([
            {
                tag: "text",
                text: `🕒 ${timeLabel}：${deployTime}`
            }
        ]);
        const normalizedIntro = Array.isArray(introLines)
            ? introLines
                .map(line => typeof line === 'string' ? line.trim() : '')
                .filter(line => line !== '')
            : [];
        if (normalizedIntro.length > 0) {
            content.push([
                {
                    tag: "text",
                    text: `\n`
                }
            ]);
            normalizedIntro.forEach(line => {
                content.push([
                    {
                        tag: "text",
                        text: line
                    }
                ]);
            });
        }
        content.push([
            {
                tag: "text",
                text: `\n`
            }
        ]);
        const ansiPattern = ansiRegex();
        const normalizeDisplay = (value, fallback = '无') => {
            if (value === undefined || value === null) {
                return fallback;
            }
            let str = String(value);
            str = str.replace(/\u001B\]8;;[^\u0007]*\u0007/g, '');
            str = str.replace(/\u001B\]8;;\u0007/g, '');
            str = str.replace(ansiPattern, '').trim();
            if (!str || str.toLowerCase() === 'undefined') {
                return fallback;
            }
            return str;
        };

        // 3. 应用列表（应用 | 说明）
        taskApps.forEach(app => {
            let branch = app.branch;
            if (Array.isArray(branch)) {
                branch = branch.join(',');
            }
            if (!branch && app.appInfo?.branch) {
                branch = app.appInfo.branch;
            }
            const typeText = normalizeDisplay(
                OPSConstant.TYPE_ALIAS_MAP[app.row?.type] || app.row?.type || '无'
            );
            const nameText = normalizeDisplay(app.row?.name || '--', '--');
            const branchText = normalizeDisplay(branch || (app.appInfo?.branch), '无');
            const descText = normalizeDisplay(app.row?.desc || app.desc, '无');
            const timeText = normalizeDisplay(app.row?.time || app.time, '--');
            content.push([
                {
                    tag: "text",
                    text: `🏷️ ${typeText} ｜ 📦 ${nameText} ｜ 🔀 ${branchText} ｜ 📝 ${descText} ｜ ⏰ ${timeText}`
                }
            ]);
        });
        const requestOption = this.buildRequestOption();
        const sendResults = [];
        for (const userId of receiveUserIds) {
            try {
                const res = await this.client.im.v1.message.create({
                    params: { receive_id_type: "user_id" },
                    data: {
                        receive_id: userId,
                        msg_type: "post",
                        content: JSON.stringify({
                            zh_cn: {
                                title: title,
                                content
                            }
                        })
                    }
                }, requestOption);
                sendResults.push({
                    userId,
                    messageId: res?.data?.message_id || ""
                });
                this.logger.success(`消息已发送到飞书个人窗口：${userId}`);
            } catch (e) {
                const detail = e?.response?.data ? JSON.stringify(e.response.data) : e.message;
                this.logger.error(`飞书个人推送失败（${userId}）：${detail}`);
            }
        }
        if (sendResults.length === 0) {
            throw new Error("未能成功发送任何飞书个人消息");
        }
        return sendResults;
    }

    /**
     * 发送 push 提交摘要
     * @param {Object} payload
     * @param {string[]} payload.commitMessages 提交消息
     * @param {string} payload.repoName 仓库名称
     * @param {string} payload.branch 本地分支
     * @param {string} payload.remoteBranch 远端分支
     * @param {string} payload.remoteName 远端名称
     * @param {string} payload.remoteUrl 远端地址
     * @param {string} payload.introText 开场说明
     * @param {string} payload.footerText 结尾说明
     * @param {string} payload.contributor 贡献者（本地 git 用户名）
     */
    async sendCommitDigest(payload = {}) {
        const {
            commitMessages = [],
            repoName = '未知仓库',
            branch = '',
            remoteBranch = '',
            remoteName = '',
            remoteUrl = '',
            introText = '[N]ew [B]uild 脚本已更新',
            footerText = '使用任意指令，即可自动更新',
            contributor = ''
        } = payload || {};
        const sanitizedMessages = (Array.isArray(commitMessages) ? commitMessages : [])
            .map(message => (typeof message === 'string' ? message.trim() : ''))
            .filter(message => !!message);
        if (sanitizedMessages.length === 0) {
            this.logger.warn('没有可发送的 commit 信息，跳过飞书通知');
            return;
        }
        const ansiPattern = ansiRegex();
        const sanitizePlainText = (value, fallback = '') => {
            if (value === undefined || value === null) {
                return fallback;
            }
            let normalized = String(value);
            normalized = normalized.replace(/\u001B\]8;;[^\u0007]*\u0007/g, '');
            normalized = normalized.replace(/\u001B\]8;;\u0007/g, '');
            normalized = normalized.replace(ansiPattern, '').trim();
            return normalized || fallback;
        };
        const contributorName = sanitizePlainText(
            contributor || this.resolveGitUserName(),
            '未知贡献者'
        );
        const content = [];
        // if (introText) {
        //     content.push([{tag: 'text', text: introText}]);
        // }
        const nowText = DateUtil.nowFull();
        content.push([{tag: 'text', text: `📦 仓库：${repoName}`}]);
        content.push([{tag: 'text', text: `🙋 贡献者：${contributorName}`}]);
        if (branch || remoteBranch) {
            const relation = branch && remoteBranch ? `${branch} → ${remoteBranch}` : (branch || remoteBranch);
            content.push([{tag: 'text', text: `🌿 分支：${relation}`}]);
        }
        if (remoteName || remoteUrl) {
            const remoteInfo = [remoteName, remoteUrl].filter(Boolean).join(' ｜ ');
            content.push([{tag: 'text', text: `🌐 远端：${remoteInfo}`}]);
        }
        content.push([{tag: 'text', text: `🕒 推送时间：${nowText}`}]);
        content.push([{tag: 'text', text: ``}]);
        content.push([{tag: 'text', text: `📝 本次包含 ${sanitizedMessages.length} 个 新改动：`}]);
        sanitizedMessages.forEach((message, index) => {
            const normalized = sanitizePlainText(message, '--');
            content.push([{tag: 'text', text: `${index + 1}. ${normalized || '--'}`}]);
        });
        content.push([{tag: 'text', text: ``}]);

        if (footerText) {
            content.push([{tag: 'text', text: footerText}]);
        }
        try {
            const requestOption = this.buildRequestOption();
            await this.client.im.v1.message.create({
                params: {receive_id_type: 'chat_id'},
                data: {
                    receive_id: this.chatId,
                    msg_type: 'post',
                    content: JSON.stringify({
                        zh_cn: {
                            title: introText,
                            content
                        }
                    })
                }
            }, requestOption);
            this.logger.success('Push 提交摘要已发送到飞书');
        } catch (e) {
            this.logger.error('Push 提交摘要发送失败:', e.response?.data || e.message);
            throw e;
        }
    }

    /**
     * 根据邮箱列表批量获取飞书 user_id
     * @param {string[]} emails 邮箱列表
     * @returns {Promise<string[]>}
     */
    async fetchUserIdsByEmails(emails = []) {
        const uniqueEmails = Array.from(new Set(
            (emails || []).map(email => email?.trim()).filter(email => !!email)
        ));
        if (uniqueEmails.length === 0) {
            return [];
        }
        try {
            const requestOption = this.buildRequestOption();
            const res = await this.client.contact.v3.user.batchGetId({
                params: {
                    user_id_type: "user_id"
                },
                data: {
                    emails: uniqueEmails
                }
            }, requestOption);
            const userList = res?.data?.user_list ?? res?.data?.items ?? [];
            const userIds = userList
                .map(item => item?.user_id)
                .filter(id => !!id);
            const invalidEmails = res?.data?.invalid_emails ?? res?.data?.not_found_emails ?? [];
            if (invalidEmails.length > 0) {
                this.logger.warn(`飞书接口未识别以下邮箱：${invalidEmails.join(', ')}`);
            }
            return Array.from(new Set(userIds));
        } catch (e) {
            const detail = e?.response?.data ? JSON.stringify(e.response.data) : e.message;
            this.logger.error(`获取飞书用户ID失败: ${detail}`);
            return [];
        }
    }

    async fetchChatMemberIds(chatId = this.chatId) {
        const memberIds = new Set();
        if (!chatId) {
            return memberIds;
        }
        try {
            const requestOption = this.buildRequestOption();
            const iterator = await this.client.im.v1.chatMembers.getWithIterator({
                path: {chat_id: chatId},
                params: {member_id_type: 'user_id'}
            }, requestOption);
            for await (const item of iterator) {
                const memberId = item?.member_id;
                if (memberId) {
                    memberIds.add(memberId);
                }
            }
        } catch (e) {
            const detail = e?.response?.data ? JSON.stringify(e.response.data) : e.message;
            this.logger.warn(`获取飞书群成员失败: ${detail}`);
        }
        return memberIds;
    }

    async addMembersToChat(userIds = [], chatId = this.chatId) {
        const uniqueIds = Array.from(new Set((userIds || []).map(id => id?.trim()).filter(id => !!id)));
        if (!chatId || uniqueIds.length === 0) {
            return false;
        }
        try {
            this.logger.info(`准备拉群，目标群: ${chatId}，user_id 列表: ${uniqueIds.join(', ')}`);
            const requestOption = this.buildRequestOption();
            const res = await this.client.im.v1.chatMembers.create({
                path: {chat_id: chatId},
                params: {
                    member_id_type: 'user_id',
                    succeed_type: 0
                },
                data: {
                    id_list: uniqueIds
                }
            }, requestOption);
            const responsePayload = res?.data ?? res ?? {};
            this.logger.success(`已提交飞书拉群申请，人数：${uniqueIds.length}，响应: ${JSON.stringify(responsePayload)}`);
            return true;
        } catch (e) {
            const detail = e?.response?.data ? JSON.stringify(e.response.data) : e.message;
            this.logger.error(`飞书拉群失败: ${detail}`);
            return false;
        }
    }

    resolveGitUserName(cwd = process.cwd()) {
        try {
            const output = execSync("git config --get user.name", {
                cwd,
                encoding: "utf-8"
            });
            const userName = (output || "").toString().trim();
            if (!userName) {
                this.logger.debug("git config user.name 为空");
            }
            return userName;
        } catch (e) {
            this.logger.debug(`读取 git 用户名失败: ${e.message}`);
            return "";
        }
    }


}
